package dbs

import (
	"crypto/md5"
	"database/sql"
	"encoding/hex"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"ups/tools"

	_ "github.com/mattn/go-sqlite3"
)

func InitEnv() {
	db, err := sql.Open("sqlite3", tools.FN_DB)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer db.Close()

	if !tools.FileExists(tools.FN_DB) {
		str := `DROP TABLE IF EXISTS FILES;
CREATE TABLE FILES(NAME TEXT PRIMARY KEY, MD5 TEXT, VER TEXT, CTM TEXT, CTX BLOB);`
		_, err = db.Exec(str)

		if err != nil {
			fmt.Println(err.Error())
		}

		fmt.Println("数据表创建完毕！")
	}
}

func GetContent(fileName string) *FileCtx {
	db, err := sql.Open("sqlite3", tools.FN_DB)
	if err != nil {
		fmt.Println(err.Error())
		return nil
	}
	defer db.Close()

	var name string
	var md5 string
	var ver string
	var ctm string
	var ctx []byte
	row := db.QueryRow("select * from files where name=?", fileName)
	err = row.Scan(&name, &md5, &ver, &ctm, &ctx)
	if err != nil {
		return nil
	}
	return &FileCtx{
		NAME: name,
		MD5:  md5,
		VER:  ver,
		CTM:  ctm,
		CTX:  ctx,
	}
}

func GetFiles(pathName string) []FileNoCtx {
	db, err := sql.Open("sqlite3", tools.FN_DB)
	if err != nil {
		fmt.Println(err.Error())
		return nil
	}
	defer db.Close()

	var ffs []FileNoCtx
	rows, err := db.Query("select name, md5, ver, ctm from files where name like ?", pathName+"%")
	if err != nil {
		fmt.Println("GetFiles:" + err.Error())
		return nil
	}
	defer rows.Close()

	for rows.Next() {
		var name string
		var md5 string
		var ver string
		var ctm string
		err = rows.Scan(&name, &md5, &ver, &ctm)
		if err != nil {
			fmt.Println("GetFiles:" + err.Error())
		} else {
			ff := FileNoCtx{
				NAME: name,
				MD5:  md5,
				VER:  ver,
				CTM:  ctm,
			}
			ffs = append(ffs, ff)
		}
	}
	return ffs
}

func BuildFiles(path string) ([]FileCtx, error) {
	var files []FileCtx
	err := filepath.Walk(path, func(filename string, fi os.FileInfo, err error) error {
		if fi.IsDir() {
			return nil
		}
		if (filename == tools.FN_DB) || (filename == tools.FN_EXE) {
			return nil
		}
		bytes, ee := os.ReadFile(filename)
		if ee != nil {
			return fmt.Errorf("读取文件[%s]错误:%s", filename, err.Error())
		}

		md := md5.New()
		md.Write(bytes)
		str := hex.EncodeToString(md.Sum(nil))
		ff := FileCtx{
			NAME: filename,
			MD5:  str,
			CTM:  fi.ModTime().Format("2006-01-02 15:04:05"),
			VER:  tools.GetExeVer(filename),
			CTX:  bytes,
		}
		files = append(files, ff)
		return nil
	})
	return files, err
}

func SaveFiles(files []FileCtx) bool {
	db, err := sql.Open("sqlite3", tools.FN_DB)
	if err != nil {
		log.Println(err.Error())
		return false
	}
	defer db.Close()

	log.Println("==================================================")
	for idx, ff := range files {
		str := "select count(*) from files where name=?"
		row := db.QueryRow(str, ff.NAME)
		var cnt int
		row.Scan(&cnt)
		if cnt == 0 {
			str = "insert into files(md5, ver, ctm, ctx, name) values(?, ?, ?, ?, ?)"
		} else {
			str = "update files set md5 = ?, ver = ?, ctm = ?, ctx=? where name = ?"
		}
		_, err = db.Exec(str, ff.MD5, ff.VER, ff.CTM, ff.CTX, ff.NAME)
		if err != nil {
			log.Printf("*ERR-[%d][%s]\n%s\n", idx, ff.NAME, err.Error())
		} else {
			log.Printf("DONE-[%d][%s].\n", idx, ff.NAME)
		}
	}
	log.Println("==================================================")
	return true
}
